package com.um.springboot.starter.utils;


import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.rmi.ConnectException;
import java.util.List;
import java.util.Map;

@Slf4j
public class NetUtil {

	public static String httpsGet(String requestUrl,String params) {

		String jsonstr = "{}";
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);

			String requestMethod = "GET";

			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != params) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(params.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonstr = buffer.toString();
		} catch (ConnectException ce) {
			log.error("", ce);
		} catch (Exception e) {
			log.error("", e);
		}
		return jsonstr;
	}



	public static String httpsPost(String requestUrl, String params) {
		String jsonstr = "{}";
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);

			String requestMethod = "POST";

			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != params) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(params.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonstr = buffer.toString();
		} catch (ConnectException ce) {
			log.error("", ce);
		} catch (Exception e) {
			log.error("", e);
		}
		return jsonstr;
	}
	/**
	 * HTTP POST 提交
	 * @param sendUrl 请求的URL
	 * @param sendParam 请求的参数
	 * @param backEncodType 请求的编码
	 * @return
	 */
	public static Object post(String sendUrl, String sendParam,String backEncodType) {
		HttpURLConnection URLConn = null;
		OutputStreamWriter outStream = null;
		String body = null;
		try {
			if (backEncodType == null || backEncodType.equals("")) {
				backEncodType = "UTF-8";
			}
			URL url = new URL(sendUrl);
			URLConn = (HttpURLConnection) url.openConnection();
			URLConn.setUseCaches(false);
			URLConn.setDoOutput(true);
			URLConn.setRequestMethod("POST");
			URLConn.setRequestProperty("Connection", "Keep-Alive");
			URLConn.setRequestProperty("Charset", backEncodType);
			URLConn.setRequestProperty("Content-Type", "text/html");
			URLConn.setRequestProperty("Content-Length", String.valueOf(sendParam.getBytes().length));
			outStream = new OutputStreamWriter(URLConn.getOutputStream(),backEncodType);
			outStream.write(sendParam);
			outStream.flush();
			if (URLConn.getResponseCode() == 200) {				
				InputStream inputStream = URLConn.getInputStream();
				body = IOUtils.toString(inputStream, backEncodType);
			}
		} catch (Exception e) {
			body = e.getMessage();
			log.error("", e);
		} finally {
			if (null != outStream) {
				try {
					outStream.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
			if (null != URLConn) {
				URLConn.disconnect();
			}
		}
		return body;
	}
	
	/**
	 * HTTP POST 提交
	 * @param sendUrl 请求的URL
	 * @param sendParam 请求的参数
	 * @param backEncodType 请求的编码
	 * @return
	 */
	public static Object post(String sendUrl, String sendParam,String contentType,String backEncodType) {
		HttpURLConnection URLConn = null;
		OutputStreamWriter outStream = null;
		String body = null;
		try {
			if (backEncodType == null || backEncodType.equals("")) {
				backEncodType = "UTF-8";
			}
			URL url = new URL(sendUrl);
			URLConn = (HttpURLConnection) url.openConnection();
			URLConn.setUseCaches(false);
			URLConn.setDoOutput(true);
			URLConn.setRequestMethod("POST");
			URLConn.setRequestProperty("Connection", "Keep-Alive");
			URLConn.setRequestProperty("Charset", backEncodType);
			URLConn.setRequestProperty("Content-Type", contentType);
			URLConn.setRequestProperty("Content-Length", String.valueOf(sendParam.getBytes().length));
			outStream = new OutputStreamWriter(URLConn.getOutputStream(),backEncodType);
			outStream.write(sendParam);
			outStream.flush();
			if (URLConn.getResponseCode() == 200) {				
				InputStream inputStream = URLConn.getInputStream();
				body = IOUtils.toString(inputStream, backEncodType);
			}
		} catch (Exception e) {
			body = e.getMessage();
			log.error("", e);
		} finally {
			if (null != outStream) {
				try {
					outStream.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
			if (null != URLConn) {
				URLConn.disconnect();
			}
		}
		return body;
	}


	/**
	 * 向指定URL发送GET方法的请求
	 *
	 * @param url
	 *            发送请求的URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url, String param) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlNameString = url + "?" + param;
			URL realUrl = new URL(urlNameString);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			// 获取所有响应头字段
			Map<String, List<String>> map = connection.getHeaderFields();
			log.debug("{}", map);
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			log.error("发送GET请求出现异常！", e);
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				log.error("", e2);
			}
		}
		return result;
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			log.error("发送 POST 请求出现异常！", e);
		}
		//使用finally块来关闭输出流、输入流
		finally{
			try{
				if(out!=null){
					out.close();
				}
				if(in!=null){
					in.close();
				}
			}
			catch(IOException ex){
				log.error("", ex);
			}
		}
		return result;
	}


	/**
	 * 提交spring boot post请求的方式
	 * @param url
	 * @param json
	 * @return
	 */
      public static JSONObject doPost(String url, JSONObject json){
		 DefaultHttpClient client = new DefaultHttpClient();
		 HttpPost post = new HttpPost(url);
		 JSONObject response = null;
		 try {
				 StringEntity s = new StringEntity(json.toString(),HTTP.UTF_8);
				 s.setContentType("application/json");//发送json数据需要设置contentType
				 post.setEntity(s);
				 HttpResponse res = client.execute(post);
				 if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
						 HttpEntity entity = res.getEntity();
						 String result = EntityUtils.toString(res.getEntity());// 返回json格式：
						 response = JSONObject.parseObject(result);
					 }
			 } catch (Exception e) {
				 throw new RuntimeException(e);
			 }
		 return response;
	 }

	/**
	 * 获取用户真实IP地址，不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
	 * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值
	 *
	 * @return ip
	 */
	public static String getRealIP(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值，第一个ip才是真实ip
			if( ip.indexOf(",")!=-1 ){
				ip = ip.split(",")[0];
			}
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
			logIp("Proxy-Client-IP", ip);
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
			logIp("WL-Proxy-Client-IP", ip);
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
			logIp("HTTP_CLIENT_IP", ip);
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
			logIp("HTTP_X_FORWARDED_FOR", ip);
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Real-IP");
			logIp("X-Real-IP", ip);
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
			logIp("getRemoteAddr", ip);
		}
		return ip;
	}

	/**
	 * 如果IP不为空则记录IP日志
	 *
	 * @param name
	 * @param ip
	 */
	private static void logIp(String name, String ip) {
		if (ip != null) {
			log.debug("{}: {}", name, ip);
		}
	}

}
